나이스페이 본인인증 서비스를 프론트엔드에 통합하기 위한 핵심 가이드
사용자 클릭 → 본인인증 팝업 → 인증 완료 → 사용자 정보 수신의 플로우를 구현합니다. 백엔드는 암호화/복호화를 담당하고, 프론트는 팝업 관리와 데이터 전달을 담당합니다.
1. POST /api/nice/auth/request
→ 암호화된 인증 데이터 받기 (tokenVersionId, encData, integrityValue)
2. form POST → NICE 팝업
→ 사용자 본인인증 진행
3. 콜백 → postMessage → POST /api/nice/auth/callback
→ 복호화된 사용자 정보 수신 (이름, 생년월일, 휴대폰, CI/DI 등)
POST /api/nice/auth/request
Content-Type: application/json
{
"requestno": "REQ1234567890",
"authtype": "M", // M: 휴대폰, C: 카드, X: 아이핀
"returnurl": "https://example.com/niceauth-callback"
}
Response:
{
"success": true,
"data": {
"tokenVersionId": "20250113...",
"encData": "BASE64_ENCRYPTED_DATA",
"integrityValue": "HMAC_SHA256_VALUE"
}
}
POST /api/nice/auth/callback
Content-Type: application/json
{
"enc_data": "RETURN_ENC_DATA",
"integrity_value": "RETURN_INTEGRITY_VALUE",
"token_version_id": "20250113..."
}
Response:
{
"success": true,
"data": {
"dataBody": {
"name": "홍길동",
"birthdate": "19900101",
"gender": "1",
"mobileno": "01012345678",
"mobileco": "SKT",
"nationalinfo": "0",
"ci": "CI_BASE64_STRING",
"di": "DI_BASE64_STRING"
}
}
}
async function requestNiceAuth(authType: 'M' | 'C' | 'X') {
// 1) 백엔드에 암호화 데이터 요청
const res = await fetch('/api/nice/auth/request', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
requestno: `REQ${Date.now()}`,
authtype: authType,
returnurl: `${location.origin}/niceauth-callback`
})
});
const json = await res.json();
if (!json.success) throw new Error(json.message);
const { tokenVersionId, encData, integrityValue } = json.data;
// 2) NICE 팝업 열기 (form POST 방식)
const form = document.createElement('form');
form.method = 'POST';
form.action = 'https://nice.checkplus.co.kr/CheckPlusSafeModel/checkplus.cb';
form.target = 'nice_popup';
const fields = {
m: 'service',
token_version_id: tokenVersionId,
enc_data: encData,
integrity_value: integrityValue
};
Object.entries(fields).forEach(([k, v]) => {
const input = document.createElement('input');
input.type = 'hidden';
input.name = k;
input.value = v as string;
form.appendChild(input);
});
document.body.appendChild(form);
const popup = window.open('', 'nice_popup', 'width=500,height=600');
if (!popup) {
alert('팝업 차단됨 - 브라우저 팝업 허용 필요');
return;
}
form.submit();
document.body.removeChild(form);
}
useEffect(() => {
const handleMessage = async (event: MessageEvent) => {
// 보안: origin 체크
if (event.origin !== window.location.origin) return;
if (event.data?.type === 'NICE_AUTH_RESULT') {
const { enc_data, integrity_value, token_version_id } = event.data.data;
// 백엔드에 복호화 요청
const res = await fetch('/api/nice/auth/callback', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({ enc_data, integrity_value, token_version_id })
});
const result = await res.json();
if (result.success) {
// 사용자 정보 사용 (result.data.dataBody)
console.log('인증 성공:', result.data.dataBody);
}
}
};
window.addEventListener('message', handleMessage);
return () => window.removeEventListener('message', handleMessage);
}, []);
파일 위치: /app/niceauth-callback/page.tsx (인증 미적용)
'use client';
import { useEffect } from 'react';
import { useSearchParams } from 'next/navigation';
export default function NiceAuthCallbackPage() {
const params = useSearchParams();
useEffect(() => {
const enc_data = params.get('enc_data');
const integrity_value = params.get('integrity_value');
const token_version_id = params.get('token_version_id');
if (window.opener && !window.opener.closed) {
window.opener.postMessage(
{
type: 'NICE_AUTH_RESULT',
data: { enc_data, integrity_value, token_version_id }
},
window.location.origin
);
}
setTimeout(() => window.close(), 500);
}, [params]);
return (
<div className="p-8 text-center">
<p>인증 처리 중...</p>
<p className="text-sm text-gray-500">창이 자동으로 닫힙니다.</p>
</div>
);
}
// ❌ 빌드 실패 (SSR 시 useSearchParams 에러)
export default function Page() {
const params = useSearchParams(); // prerender 에러
}
// ✅ 해결
'use client'; // 클라이언트 컴포넌트로 명시
export default function Page() {
const params = useSearchParams();
}
event.origin === window.location.originyour-project/
├── app/
│ ├── (dashboard)/
│ │ └── signup/
│ │ └── page.tsx # 본인인증 요청 버튼 위치
│ └── niceauth-callback/
│ └── page.tsx # 콜백 (퍼블릭)
└── lib/
└── utils/
└── niceAuth.ts # 유틸 함수
/app/niceauth-callback/page.tsx)requestNiceAuth() 연결백엔드 API 관련 문의: [백엔드팀]
프론트 구현 참고: /apps/akc-b2c-admin/src/app/(dashboard)/niceauth/